package com.study.example.gameserver.console;

import com.google.common.collect.Lists;
import com.sparrow.cache.entity.EntityCache;
import com.sparrow.cache.persist.PersistElement;
import com.sparrow.cache.persist.PersistWorker;
import com.sparrow.cache.service.CacheService;
import com.sparrow.common.ai.findpath.PathNode;
import com.sparrow.common.ai.findpath.impl.AStar;
import com.sparrow.common.aoi.domain.MapData;
import com.sparrow.common.aoi.util.MapUtil;
import com.sparrow.common.console.annotation.Command;
import com.sparrow.common.util.JsonUtil;
import com.sparrow.common.util.WordUtil;
import com.sparrow.event.api.EventBus;
import com.sparrow.rpc.future.SettableRpcFuture;
import com.sparrow.rpc.socket.session.RpcClientSessionManager;
import com.sparrow.rpc.socket.session.RpcSession;
import com.sparrow.rpc.util.RpcUtil;
import com.study.example.gameserver.base.ConfigService;
import com.study.example.gameserver.config.MonsterResource;
import com.sparrow.common.hotswap.HotSwapService;
import com.study.example.gameserver.module.scene.domain.SceneMap;
import com.study.example.gameserver.module.scene.manager.SceneManager;
import com.study.example.gameserver.module.player.service.PlayerService;
import com.study.example.gameserver.module.player.entity.PlayerEntity;
import com.study.example.gameserver.module.test.ITestRpcFacade;
import com.sparrow.resource.cache.ResourceCache;
import com.sparrow.rpc.callback.RpcCallback;
import com.sparrow.rpc.future.RpcFuture;
import com.sparrow.rpc.service.RpcService;
import com.study.example.gameserver.serverinfo.service.ServerInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class ConsoleCommandFacade {
    @Autowired
    private EntityCache<Long, PlayerEntity> playerBaseInfoCache;
    @Autowired
    private ServerInfoService serverInfoService;

    @Autowired
    private CacheService cacheService;
    @Autowired
    private EventBus eventBus;
    @Autowired
    private HotSwapService hotSwapService;
    @Autowired
    private PlayerService playerService;
    @Autowired
    private RpcService rpcService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private ResourceCache<Integer, MonsterResource> monsterResourceCache;

    @Autowired
    private ApplicationContext context;

    @Command(cmd = "map", desc = "test command")
    public void map() {
        SceneManager sceneManager = context.getBean(SceneManager.class);
        SceneMap sceneMap = sceneManager.getSceneMap(MapUtil.toMapId(1, 1));
        MapData mapData = sceneMap.getMapData();
        int width = mapData.getWidth();
        int height = mapData.getHeight();
        System.out.println("不可走点列表：");
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (!mapData.isWalkable(x, y)) {
                    System.out.println("x=" + x + " y=" + y);
                }
            }
        }
    }

    @Command(cmd = "test", desc = "test command")
    public void test() {
        SceneManager sceneManager = context.getBean(SceneManager.class);
        SceneMap sceneMap = sceneManager.getSceneMap(1, 1);
        MapData mapData = sceneMap.getMapData();
        AStar aStar = new AStar();
        for (int i = 0; i < mapData.getHeight(); i++) {
            for (int j = 0; j < mapData.getWidth(); j++) {
                if (!aStar.canMove(mapData.getWalkable(), new PathNode(j, i))) {
                    System.out.println(String.format("不可走点 x=%d y=%d Astar判断可走=%b", j, i, aStar.canMove(mapData.getWalkable(), new PathNode(j, i))));
                }
            }
        }
    }

    @Command(cmd = "insert", desc = "test command")
    public void insert() {
        for (int i = 1; i <= 1000; i++) {
            int finalI = i;
            PlayerEntity playerBaseInfo = cacheService.getOrCreate(PlayerEntity.class, Long.valueOf(i), e -> {
                e.setAccount("a" + finalI);
                e.setName("a" + finalI);
                e.setServer(configService.getServerId());
            });
        }
    }

    @Command(cmd = "update", desc = "test command")
    public void update() {
        for (int i = 1; i <= 1000; i++) {
            int finalI = i;
            PlayerEntity playerBaseInfo = cacheService.get(PlayerEntity.class, (long)finalI);
            if (playerBaseInfo == null) {
            } else {
                playerBaseInfo.update();
                playerBaseInfo.update();
            }
        }
    }

    @Command(cmd = "delete", desc = "test command")
    public void delete() {
        for (PlayerEntity playerBaseInfo : playerBaseInfoCache.list()) {
            playerBaseInfoCache.delete(playerBaseInfo.getPK());
        }
        System.out.println("delete");
    }

    @Command(cmd = "dbstat", desc = "test command")
    public void dbstat() {
        CacheService service = context.getBean(CacheService.class);
        Set<PersistWorker> set = service.getAllPersistWorker();
        for (PersistWorker w : set) {
            System.out.println("PersistWorker name:" + w.getName());
            Collection<PersistElement> elements = w.waitElements();
            for (PersistElement element : elements) {
                System.out.println("element:" + element.getPK() + " state:" + element.getState());
            }
        }
        System.out.println("========================处于DelayMergeWriteBack的实体==============================");

    }

    @Command(cmd = "stop", desc = "stop server")
    public void stop() {
        System.out.println("执行关服命令");
        System.exit(0);
    }

    @Command(cmd = "c1")
    public void c1() {
        MonsterResource resource = monsterResourceCache.getResource(1);
        System.out.println(JsonUtil.toJSON(resource));
    }

    @Command(cmd = "c2")
    public void c2() {
        ResourceCache<Integer, MonsterResource> cache = (ResourceCache<Integer, MonsterResource>) context.getBean("monsterResourceCache");
        System.out.println(JsonUtil.toJSON(cache.getResource(1)));
    }

    @Command(cmd = "c3")
    public void c3() {
        ResourceCache<Integer, MonsterResource> cache = (ResourceCache<Integer, MonsterResource>) context.getBean("monsterResourceCache");
        List<MonsterResource> list = cache.getAllResource();
        for (MonsterResource e : list) {
            System.out.println(JsonUtil.toJSON(e));
        }
    }

    @Command(cmd = "word")
    public void word() {
        WordUtil.load();

        boolean suc = WordUtil.isMatch("毛泽东");
        System.out.println(suc);
    }

    @Command(cmd = "rpc")
    public void rpc(int nodeId) {
        RpcUtil.runAsyncRpcMethod(String.valueOf(nodeId), ITestRpcFacade.class, service -> {
            RpcFuture<String> future = service.hello("hello " + nodeId);
            future.addCallback(resp -> {
                System.out.println("rpc 返回:" + resp);
            });
        });
    }

    @Command(cmd = "rpcLoop")
    public void rpcLoop(int nodeId) {
        for (int i = 0; i < 10100; i++) {
            RpcUtil.runAsyncRpcMethod(String.valueOf(nodeId), ITestRpcFacade.class, service -> {
                RpcFuture<String> future = service.hello("hello " + nodeId);
                future.addCallback(resp -> {
                    System.out.println("rpc 返回:" + resp);
                });
            });
        }
    }

    @Command(cmd = "rpcsession")
    public void rpcsession() {
        System.out.println("rpc client session");
        for (RpcSession session : context.getBean(RpcClientSessionManager.class).getAllSession()) {
            System.out.println(session.getIdentity());
        }
    }


    @Command(cmd = "rpc1")
    public void rpc1() {
        RpcUtil.runAsyncRpcMethod("1", ITestRpcFacade.class, service -> {
            RpcFuture<String> future = service.hello("hello");
            future.addCallback(resp -> {
                System.out.println("rpc 返回:" + resp);
            });
        });
    }

    @Command(cmd = "rpc11")
    public void rpc11() {
        RpcUtil.runAsyncRpcMethod("2", ITestRpcFacade.class, service -> {
            RpcFuture<String> future = service.hello("hello");
            future.addCallback(resp -> {
                System.out.println("rpc 返回:" + resp);
            });
        });
    }

    @Command(cmd = "rpc2")
    public void rpc2() {
        RpcUtil.runAsyncRpcMethod("1", ITestRpcFacade.class, service -> {
            service.testVoid(Lists.newArrayList("hello1", "hello2"));
        });
    }

    @Command(cmd = "rpc3")
    public void rpc3() {
        ITestRpcFacade rpcFacade = rpcService.getProxy("1", ITestRpcFacade.class);
        RpcFuture<String> f = rpcFacade.testSync();
        try {
            String result = f.sync(3000, TimeUnit.SECONDS);
            System.out.println("调用方获得结果:" + result);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    @Command(cmd = "rpc4")
    public void rpc4() {
        ITestRpcFacade rpcFacade = rpcService.getProxy("1", ITestRpcFacade.class);
        RpcFuture<String> f = rpcFacade.testTimeOut();
        f.addCallback(new RpcCallback<String>() {
            @Override
            public void onResponse(String s) {
                System.out.println("rpc结果：" + s);
            }

            @Override
            public void onError(Throwable t) {
                t.printStackTrace();
            }
        });
    }

    @Command(cmd = "rpc5")
    public void rpc5() {
        ITestRpcFacade rpcFacade = rpcService.getProxy("1", ITestRpcFacade.class);
        SettableRpcFuture<String> f = rpcFacade.testSettable("hello");
        f.addCallback(new RpcCallback<String>() {
            @Override
            public void onResponse(String s) {
                System.out.println("rpc结果：" + s);
            }

            @Override
            public void onError(Throwable t) {
                t.printStackTrace();
            }
        });
    }

    @Command(cmd = "info")
    public void info() {
        TestObj test = serverInfoService.getObject(1, "test", TestObj.class);
        test.setAge(test.getAge() + 1);
        serverInfoService.saveObject(1, "test", test);
        test = serverInfoService.getObject(1, "test", TestObj.class);
        System.out.println("getTest:" + JsonUtil.toJSON(test));
    }



    public static class TestObj {
        private int age;

        public void setAge(int age) {
            this.age = age;
        }

        public int getAge() {
            return age;
        }
    }
}
